#ifndef _SHD_DOMAIN_HLSL_
#define _SHD_DOMAIN_HLSL_

#include "./shd_hull.hlsl"

//--------------------------------------------------------------------------------------
// Evaluation domain shader section
//--------------------------------------------------------------------------------------
struct DS_OUTPUT {
	int	vIndex		        : INDEX;
	float4 vPosition        : SV_POSITION;
	float3 vWorldPos        : WORLDPOS;
	float3 vColor			: COLOR;
	float3 vNormal			: NORMAL;
};

// The domain shader is run once per vertex and calculates the final vertex's position
// and attributes.  It receives the UVW from the fixed function tessellator and the
// control point outputs from the hull shader.  Since we are using the DirectX 11
// Tessellation pipeline, it is the domain shader's responsibility to calculate the
// final SV_POSITION for each vertex.  In this sample, we evaluate the vertex's
// position using a Bernstein polynomial and the normal is calculated as the cross
// product of the U and V derivatives.

// The input SV_DomainLocation to the domain shader comes from fixed function
// tessellator.  And the OutputPatch comes from the hull shader.  From these, you
// must calculate the final vertex position, color, texcoords, and other attributes.

// The output from the domain shader will be a vertex that will go to the video card's
// rasterization pipeline and get drawn to the screen.

[domain("quad")]
DS_OUTPUT DS( HS_CONSTANT_DATA_OUTPUT input, 
					float2 UV : SV_DomainLocation,
					const OutputPatch<HS_OUTPUT, OUTPUT_PATCH_SIZE> inputPatch ) {
	/**********************************************************************
	* This DS will have be compiled once for each of these defines.       *
	* The binaries will be selected at runtime by the ComboBox on the GUI *
	**********************************************************************/ 
	DS_OUTPUT Output;

	// this is the position of the vertex on the current surface(will be tranformed w/wvp)
	float3 position = float3(0.0,0.0,0.0);
	int index = 0;
	index = inputPatch[UV.x].vIndex;

//	Output.vColor = float3( 1.0, 0.0, 0.0 );
	Output.vColor = float3( 1.0, ( (float) index ) / g_iQttControlPoints , 0.1 );

	/****** Sphere ******/
#if defined(SPHERE)

	if( index < g_iQttControlPoints-1 ){
		float3 tangent = inputPatch[UV.x].vTangent;
		float distance = sqrt( dot( tangent, tangent ) );
		tangent = normalize( tangent );

		float3 up = float3( 0.0, 1.0, 0.0 );
		float3 normal = cross( tangent, up );
		float vect_module = sqrt( dot( normal, normal ) );
		if( vect_module <= 0.010 ) { // tangent is very close to the up vector
			normal = float3( 0.0, 0.0, 1.0 );
		}
		normal = normalize( normal );
		float3 binormal = normalize( cross( tangent, normal ) );
		normal = normalize( cross( binormal, tangent ) ); // ensures orthogonality

		float pi2 = 6.28318530;
		float R = g_fRadius;
		float H = distance;
		float S = UV.x;
		float T = UV.y;
		float theta = pi2*S;
		float sinTheta,cosTheta;
		sincos( theta, sinTheta, cosTheta );
		position = R*cosTheta*normal + R*sinTheta*binormal + T*H*tangent;

		Output.vNormal = normalize( R*cosTheta*normal + R*sinTheta*binormal );

		float3 center = inputPatch[UV.x].vPosition;
		position += center;
	}

	/******* End Sphere *******/

	/****** Cone ******/
#elif defined(CONE)
	float pi2 = 6.28318530;
	float pi = pi2/2;
	float R = 0.5;
	float H = 1.5;
	float S = UV.y;
	float T = UV.x;
	float theta = pi2*T;
	float sinTheta,cosTheta;

	sincos( theta, sinTheta, cosTheta );

	position = float3( ((H-S*H)/H)*R*cosTheta, ((H-S*H)/H)*R*sinTheta, S*H );

	Output.vColor = float3( normalize(position) + 0.4 );
	/****** End Cone ******/

#elif defined(TORUS)
	/****** Torus ******/
	float pi2 = 6.28318530;
	float M = 1;
	float N = 0.5;
	float cosS, sinS;
	sincos( pi2 * UV.x, sinS, cosS );
	float cosT, sinT;
	sincos( pi2 * UV.y, sinT, cosT );

	position = float3((M + N * cosT) * cosS, (M + N * cosT) * sinS, N * sinT);

	Output.vColor = float3(normalize(position) + 0.4);
	/****** End Torus ******/

#elif defined(CYLINDER)
	/****** Cylinder ******/
	float pi2 = 6.28318530;
	float pi = pi2/2;
	float R = 0.5f;
	float H = 3;
	float S = UV.x;
	float T = UV.y;
	float theta = pi2*S;
	float sinTheta,cosTheta;
	sincos( theta, sinTheta,cosTheta);
	position = float3(R*cosTheta, R*sinTheta, T*H);
	Output.vColor = float3(normalize(position) + 0.4);
	/****** End Cylinder ******/

#elif defined(TEAR)
	/****** Tear ******/
	float pi2 = 6.28318530;
	float pi = pi2/2;
	float R = 2;
	float S = UV.x;
	float T = UV.y;
	float fi = pi2*S;
	float theta = pi*T;
	float sinFi,cosFi,sinTheta,cosTheta;
	sincos( fi, sinFi, cosFi);
	sincos( theta, sinTheta,cosTheta);
	position = float3(0.5*(1 - cosTheta)*sinTheta*cosFi,
									0.5*(1 - cosTheta)*sinTheta*sinFi,
									cosTheta);
	Output.vColor = float3(normalize(position) + 0.4);
	/****** End Tear ******/

#elif defined(CROSS_CAP)
	/****** Cross-Cap ******/
	float pi2 = 6.28318530;
	float pi = pi2/2;
	float u = UV.x*pi;
	float v = UV.y*pi;
	float sinu,cosu,sinv,cosv,sin2v;
	sincos( u, sinu, cosu );
	sincos( v, sinv, cosv );
	sin2v = sin( 2*v );

	position = float3(cosu*sin2v,sinu*sin2v,cosv*cosv - cosu*cosu*sinv*sinv);
	Output.vColor = float3(normalize(position) + 0.4f);
	/****** End Cross-Cap ******/

#elif defined(STEINERS_ROMAN)
	/****** Steiners Roman ******/
	float pi2 = 6.28318530;
	float pi = pi2/2;
	float u = UV.x*pi;
	float v = UV.y*pi;
	float sinu,cosu,sinv,cosv,sin2v,sin2u;
	sincos( u, sinu, cosu );
	sincos( v, sinv, cosv );
	sin2v = sin( 2*v );
	sin2u = sin( 2*u );
	float r = 1;
	float a = 1;	
	position = float3(a*a*cosv*cosv*sin2u/2,a*a*sinu*sin2v/2,a*a*cosu*sin2v/2);
	Output.vColor = float3(normalize(position) + 0.4f);
	/****** End Steiners Roman ******/
	
#elif defined(SEA_SHELL)
	/****** Sea Shell ******/
	float pi2 = 6.28318530;
	float pi = pi2/2;
	float x,y,z;
	float s = UV.x;
	float t = UV.y;
	x = 2.0f * (1.0f - pow(2.73,(s * 6 * pi) / (6 * pi))) * cos(s * 6 * pi) * cos((t * 2 * pi) / 2) * cos((t * 2 * pi) / 2);
	y = 2.0f * (-1.0f + pow(2.73,(s * 6 * pi) / (6 * pi))) * sin(s * 6 * pi) * cos((t * 2 * pi) / 2) * cos((t * 2 * pi) / 2);
	z = 1.0f - pow(2.73,(s * 6 *pi) / (3 * pi)) - sin(t * 2 * pi) + pow(2.73,(s * 6 * pi) / (6 * pi)) * sin(t * 2 *pi);
	position = float3(x, y, z);
	Output.vColor = float3(UV.x,UV.y,UV.x*UV.y/2);
	/****** End Sea Shell ******/

#elif defined(DINI)
	/****** Dini ******/
	float pi2 = 6.28318530;
	float pi = pi2/2;
	float x,y,z;
	float s = UV.x;
	float t = UV.y;
	x = 1.0f * cos(s * 4 * pi) * sin(t + 0.01);
	y = 1.0f * sin(s * 4 * pi) * sin(t + 0.01);
	z = 1.0f * (cos(t + 0.01) + log(tan((t + 0.01) / 2))) + 0.2f * s * 4 * pi;
	position = float3(x, y, z);
	Output.vColor = float3(UV.x,UV.y,UV.x*UV.y/2);
	/****** End Dini ******/

#elif defined(HEART)
	/****** Heart ******/
	float pi2 = 6.28318530;
	float pi = pi2/2;
	float x,y,z;
	float s = UV.x;
	float t = UV.y;
	x = cos(s * pi) * sin(t * 2 * pi) - pow(abs(sin(s * pi) * sin(t * 2 * pi)), 0.5f) * 0.5f;
	y = cos(t * 2 * pi) * 0.5f;
	z = sin(s * pi) * sin(t * 2 * pi);
	position = float3(x, y, z);
	Output.vColor = float3(0.7,0,0);
	/****** End Heart ******/

#endif
    
	Output.vPosition = mul( float4(position,1), g_mViewProjection );
	Output.vWorldPos = Output.vPosition;
	Output.vIndex = index;

	return Output;
};


#endif // _SHD_DOMAIN_HLSL_
